import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
'''
 图片识别逻辑处理工具类
'''
class recognitionUtil : 
    # MIN_MATCH_COUNT = 10
    # MIN_MATCH_COUNT = 4

    def __init__(self, recognitionParam):
        # 初始图片路径
        self.queryImageUrl = recognitionParam.get('queryImageUrl') if 'groupMenuList' in recognitionParam else './feature/test3.png'
        self.originImageUrl = recognitionParam.get('queryImageUrl') if 'groupMenuList' in recognitionParam else './testp/windows.png'
        # 获取图片的规格信息
        

        # 是否调试
        self.debugMode = recognitionParam.get('debugMode') if 'debugMode' in recognitionParam else False
        #  各种常量 ： 特征点最低匹配数量
        self.MIN_MATCH_COUNT = recognitionParam.get('MIN_MATCH_COUNT') if 'MIN_MATCH_COUNT' in recognitionParam else 4
        self.FLANN_INDEX_KDTREE = recognitionParam.get('FLANN_INDEX_KDTREE') if 'FLANN_INDEX_KDTREE' in recognitionParam else 1
        self.FLANN_TREES = recognitionParam.get('FLANN_TREES') if 'FLANN_TREES' in recognitionParam else 5 
        self.FLANN_CHECKS = recognitionParam.get('FLANN_CHECKS') if 'FLANN_CHECKS' in recognitionParam else 50
        self.FLANN_K = recognitionParam.get('FLANN_K') if 'FLANN_K' in recognitionParam else 2
        # 匹配度
        self.MATHCES_DEGREE = recognitionParam.get('MATHCES_DEGREE') if 'MATHCES_DEGREE' in recognitionParam else 0.7
        pass

    # 获取识别图片所处的位置4个坐标点
    def recognitionCoordinate(self) : 
        # 获取图片
        img1 = cv.imread(self.queryImageUrl)          # queryImage
        img2 = cv.imread(self.originImageUrl) # trainImage
        # print(img1.shape)
        # print(img2.shape)
        
        # Initiate SIFT detector
        sift = cv.SIFT_create()
        # find the keypoints and descriptors with SIFT
        kp1, des1 = sift.detectAndCompute(img1,None)
        kp2, des2 = sift.detectAndCompute(img2,None)

        # 创建FLANN匹配器
        # FLANN_INDEX_KDTREE = 1
        index_params = dict(algorithm = self.FLANN_INDEX_KDTREE, trees = self.FLANN_TREES)
        # checks为int类型，是遍历次数 
        search_params = dict(checks = self.FLANN_CHECKS)
        flann = cv.FlannBasedMatcher(index_params, search_params)

        matches = flann.knnMatch(des1,des2,k=self.FLANN_K)
        # store all the good matches as per Lowe's ratio test.
        good = [] 
        resultDst = dict(points=None,centerPoint=None)
        for m,n in matches:
            if m.distance < self.MATHCES_DEGREE * n.distance:
                good.append(m)
        if len(good)>self.MIN_MATCH_COUNT:
            src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
            dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
            M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC,5.0)
            matchesMask = mask.ravel().tolist()
            # print(img1.shape)
            h,w,d = img1.shape
            pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
            dst = cv.perspectiveTransform(pts,M)
            # resultDst = dst
            resultDst['points'] = dst.tolist()
            resultDst['centerPoint'] = cv.minAreaRect(dst)
            # print(dst)
            # debug 模式将弹出图片的匹配位置
            if(self.debugMode) : 
                img2 = cv.polylines(img2,[np.int32(dst)],True,255,3, cv.LINE_AA)
        else:
            print( "Not enough matches are found - {}/{}".format(len(good), self.MIN_MATCH_COUNT) )
            matchesMask = None
        # debug 模式将弹出图片的匹配位置
        if(self.debugMode) : 
            draw_params = dict(matchColor = (0,255,0), # draw matches in green color
                            singlePointColor = None,
                            matchesMask = matchesMask, # draw only inliers
                            flags = 2)
            img3 = cv.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
            plt.imshow(img3, 'gray'),plt.show()
        return resultDst
    
    # 获取识别图片所处的位置4个坐标点
    # def recognitionCoordinate(self) : 
        # return


if __name__ == '__main__' :
    # dst = recognitionUtil(dict(debugMode=False)).recognitionCoordinate()
    dst = recognitionUtil(dict(debugMode=True)).recognitionCoordinate()
    print(dst)
    # rect = cv.minAreaRect(dst) # 得到最小外接矩形的（中心(x,y), (宽,高), 旋转角度）
    # print(rect)
    # print(type(rect))
    print('=====================================')
    # print(dst)
    # print(type(dst))
